package com.sc.nft.controller;

import cn.hutool.extra.servlet.ServletUtil;
import com.sc.nft.annotation.UserLogin;
import com.sc.nft.controller.request.IdPageRequest;
import com.sc.nft.controller.request.IdRequest;
import com.sc.nft.entity.dto.*;
import com.sc.nft.entity.vo.*;
import com.sc.nft.enums.RedisKeyEnum;
import com.sc.nft.exception.GlobalException;
import com.sc.nft.exception.GlobalRunTimeException;
import com.sc.nft.pool.UserPool;
import com.sc.nft.service.WantBuyOrderService;
import com.sc.nft.sup.PageResult;
import com.sc.nft.sup.Result;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.util.concurrent.TimeUnit;

/**
 * @author 刘国航
 * @desc
 * @since 2024/12/20 10:05
 */
@Slf4j
@RequiredArgsConstructor
@RestController
@RequestMapping("/wantBuyOrder")
@Api(tags = "求购单的后台")
public class WantBuyOrderController {

    private final WantBuyOrderService wantBuyOrderService;
    private final RedissonClient redissonClient;

    @PostMapping(value = "/enableWantBuy", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "是否开启求购", notes = "是否开启求购", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public Result<WantBuyOrderEnableVO> enableWantBuy(@Valid @RequestBody WantBuyOrderBaseDTO dto) {
        return Result.success(wantBuyOrderService.enableWantBuy(dto.getOrderType(), dto.getRelationId()));
    }

    @PostMapping(value = "/openCreate", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "打开求购单创建页面", notes = "打开求购单创建页面", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public Result<WantBuyOrderOpenCreateVO> openCreate(@Valid @RequestBody WantBuyOrderBaseDTO dto) {
        return Result.success(wantBuyOrderService.openCreate(UserPool.getUser(), dto.getOrderType(), dto.getRelationId()));
    }

    @PostMapping(value = "/create", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "创建求购单", notes = "创建求购单", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public Result create(@Valid @RequestBody WantBuyOrderCreateDTO dto, HttpServletRequest httpServletRequest) {
        wantBuyOrderService.create(UserPool.getUser(), dto, ServletUtil.getClientIP(httpServletRequest));
        return Result.success();
    }

    @PostMapping(value = "/page", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "求购单列表分页查询", notes = "求购单列表分页查询", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public PageResult<WantBuyOrderWebPageVO> page(@Valid @RequestBody WantBuyOrderWebPageDTO dto) {
        return PageResult.success(wantBuyOrderService.page(UserPool.getUser(), dto.toMp(), dto.getOrderType(), dto.getRelationId()));
    }

    @PostMapping(value = "/queryUsableWantBuyQuantity", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "获取求购数量", notes = "获取求购数量", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public Result<WantBuyOrderWebVO> queryUsableWantBuyQuantity(@Valid @RequestBody IdRequest request) {
        return Result.success(wantBuyOrderService.queryUsableWantBuyQuantity(UserPool.getUser(), request.getId()));
    }

    @PostMapping(value = "/queryHoldPage", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "获取本人拥有的藏品/道具", notes = "获取本人拥有的藏品/道具", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public PageResult<WantBuyOrderQueryHoldVO> queryHoldPage(@Valid @RequestBody IdPageRequest request) {
        return PageResult.success(wantBuyOrderService.queryHoldPage(UserPool.getUser(), request.toMp(), request.getId()));
    }

    @PostMapping(value = "/myWantBuyPage", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "我的求购列表", notes = "我的求购列表", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public PageResult<WantBuyOrderMyPageVO> myWantBuyPage(@Valid @RequestBody WantBuyOrderBasePageDTO request) {
        return PageResult.success(wantBuyOrderService.myWantBuyPage(UserPool.getUser(), request.toMp(), request.getOrderType(), request.getRelationId()));
    }

    @PostMapping(value = "/myWantBuyDetail", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "我的求购详情", notes = "我的求购详情", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public Result<WantBuyOrderMyDetailVO> myWantBuyDetail(@Valid @RequestBody IdRequest request) {
        return Result.success(wantBuyOrderService.myWantBuyDetail(request.getId()));
    }

    @PostMapping(value = "/myRecordPage", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "我的求购单成交记录", notes = "我的求购单成交记录", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public PageResult<WantBuyOrderRecordVO> myRecordPage(@Valid @RequestBody IdPageRequest request) {
        return PageResult.success(wantBuyOrderService.myRecordPage(request.toMp(), request.getId()));
    }

    @PostMapping(value = "/close", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "关闭求购单", notes = "关闭求购单", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public Result close(@Valid @RequestBody IdRequest request) {
        RLock lock = redissonClient.getLock(RedisKeyEnum.WANT_BUY_ORDER.getKey() + request.getId());
        try {
            boolean res = lock.tryLock(30, 30, TimeUnit.SECONDS);
            if (!res) {
                throw new GlobalException("操作频繁，请重试！！！！");
            }
            wantBuyOrderService.close(request.getId());
        } catch (Exception e) {
            throw new GlobalRunTimeException(e.getMessage());
        } finally {
            if (lock.isLocked() && lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
        return Result.success();
    }

    @PostMapping(value = "/sell", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "出售", notes = "出售", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public Result sell(@Valid @RequestBody WantBuyOrderSellDTO request, HttpServletRequest httpServletRequest) {
        RLock lock = redissonClient.getLock(RedisKeyEnum.WANT_BUY_ORDER.getKey() + request.getId());
        try {
            boolean res = lock.tryLock(30, 30, TimeUnit.SECONDS);
            if (!res) {
                throw new GlobalException("操作频繁，请重试！！！！");
            }
            wantBuyOrderService.sell(UserPool.getUser(), request, ServletUtil.getClientIP(httpServletRequest));
        } catch (Exception e) {
            log.error("求购单出售异常", e);
            throw new GlobalRunTimeException(e.getMessage());
        } finally {
            if (lock.isLocked() && lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
        return Result.success();
    }

    @PostMapping(value = "/income", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "计算收入", notes = "计算收入", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public Result<WantBuyOrderIncomeVO> income(@Valid @RequestBody WantBuyOrderIncomeDTO request) {
        return Result.success(wantBuyOrderService.income(UserPool.getUser(), request.getId(), request.getSize()));
    }

}
